home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / contrib / dvx / demos / ico / ico.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-15  |  27.8 KB  |  1,097 lines

  1. /* $XConsortium: ico.c,v 1.30 89/12/19 13:45:17 rws Exp $ */
  2. /***********************************************************
  3. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  4. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  5.  
  6.                         All Rights Reserved
  7.  
  8. Permission to use, copy, modify, and distribute this software and its 
  9. documentation for any purpose and without fee is hereby granted, 
  10. provided that the above copyright notice appear in all copies and that
  11. both that copyright notice and this permission notice appear in 
  12. supporting documentation, and that the names of Digital or MIT not be
  13. used in advertising or publicity pertaining to distribution of the
  14. software without specific, written prior permission.  
  15.  
  16. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  18. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  19. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  21. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  22. SOFTWARE.
  23.  
  24. ******************************************************************/
  25. /******************************************************************************
  26.  * Description
  27.  *    Display a wire-frame rotating icosahedron, with hidden lines removed
  28.  *
  29.  * Arguments:
  30.  *    -r        display on root window instead of creating a new one
  31.  *    =wxh+x+y    X geometry for new window (default 600x600 centered)
  32.  *    host:display    X display on which to run
  33.  * (plus a host of others, try -help)
  34.  *****************************************************************************/
  35. /* Additions by jimmc@sci:
  36.  *  faces and colors
  37.  *  double buffering on the display
  38.  *  additional polyhedra
  39.  *  sleep switch
  40.  */
  41.  
  42.  
  43. #if defined (PROTO) || defined(PROTO1) /* JDC 91/04/22 */
  44. #define NeedFunctionPrototypes 0
  45. #define NeedFunctionPtrPrototypes 1
  46. #include "ico.fd1"
  47. #endif
  48.  
  49. #if defined (PROTO) || defined(PROTO1) || defined(__WATCOM__) /* POHC 92/07/23 */
  50. #endif
  51. void icoFatal(char *fmt,...);
  52.  
  53. #if PROTO
  54. #include "ico.fd2"
  55. #endif
  56.  
  57. #include <X11/Xlib.h>
  58. #include <X11/Xatom.h>
  59. #include <X11/Xutil.h>
  60. #include <stdio.h>
  61. #include <stdlib.h> /* POHC 90/12/16 */
  62. #include <time.h> /* JDC */
  63. #include <stdarg.h> /* MTP 92/07/30 */
  64. #ifdef MULTIBUFFER
  65. #include <X11/extensio/multibuf.h>
  66. #endif /* MULTIBUFFER */
  67.  
  68. typedef double Transform3D[4][4];
  69.  
  70. #define MIN_ICO_WIDTH 5
  71. #define MIN_ICO_HEIGHT 5
  72. #define DEFAULT_ICO_WIDTH 150
  73. #define DEFAULT_ICO_HEIGHT 150
  74. #define DEFAULT_DELTAX 18 /* 90/06/26 POHC 13 */
  75. #define DEFAULT_DELTAY 12 /* 9 */
  76.  
  77. #include "polyinfo.h"    /* define format of one polyhedron */
  78.  
  79. /* Now include all the files which define the actual polyhedra */
  80. Polyinfo polys[] = {
  81. #include "allobjs.h"
  82. };
  83. int polysize = sizeof(polys)/sizeof(polys[0]);
  84.  
  85. typedef struct _DBufInfo { /* POHC 90/10/09 */
  86.     int prevX, prevY;
  87.     unsigned long *plane_masks;    /* points into dbpair.plane_masks */
  88.     unsigned long enplanemask;    /* what we enable for drawing */
  89.     XColor *colors;        /* size = 2 ** totalplanes */
  90.     unsigned long *pixels;    /* size = 2 ** planesperbuf */
  91. } DBufInfo;
  92.  
  93. typedef struct _DBufPair { /* POHC 90/10/09 */
  94.     int planesperbuf;
  95.     int pixelsperbuf;    /* = 1<<planesperbuf */
  96.     int totalplanes;    /* = 2*planesperbuf */
  97.     int totalpixels;    /* = 1<<totalplanes */
  98.     unsigned long *plane_masks;    /* size = totalplanes */
  99.     unsigned long pixels[1];
  100.     int dbufnum;
  101.     DBufInfo bufs[2];
  102.     DBufInfo *drawbuf, *dpybuf;
  103. } DBufPair;
  104.  
  105. DBufPair dbpair;
  106.  
  107. XColor bgcolor,fgcolor;
  108.  
  109. extern GC XCreateGC();
  110.  
  111. #if defined(SYSV) || defined(MSDOS) /* POHC 90/10/09 */
  112. #define random rand
  113. #define srandom srand
  114. #endif
  115.  
  116. #ifndef MSDOS /* JDC 91/08/08 */
  117. char    *malloc();
  118. extern long random();
  119. extern long time();
  120. #endif /* MSDOS */
  121.  
  122. char *ProgramName;
  123. Display *dpy;
  124. Window win, draw_window;
  125. int winX, winY, winW, winH;
  126. int dispW,dispH; /* POHC */
  127. int icoW = 0, icoH = 0;
  128. int icoDeltaX = DEFAULT_DELTAX, icoDeltaY = DEFAULT_DELTAY;
  129. Colormap cmap;
  130. GC gc;
  131. int multibuf = 0;
  132. #ifdef MULTIBUFFER
  133. int mbevbase, mberrbase;
  134. Multibuffer multibuffers[2];
  135. Window icowin;
  136. #endif /* MULTIBUFFER */
  137.  
  138. char *Primaries[] = {"red", "green", "blue", "yellow", "cyan", "magenta"};
  139. #define NumberPrimaries 6
  140.  
  141. int nplanesets;
  142. int dsync = 0;
  143. int softdbl = 0, dblbuf = 0;
  144. int sleepcount = 0;
  145. int msleepcount = 0;
  146. int numcolors = 0;
  147. char **colornames;    /* points into argv */
  148. int dofaces = 0;
  149. int doedges = 1;
  150. int initialized = 0; /* POHC/GWP */
  151.  
  152. Polyinfo *findpoly();
  153.  
  154. static char *help_message[] = {
  155. "where options include:",
  156. "    -display host:dpy            X server to use",
  157. "    -geometry geom               geometry of window to use",
  158. "    -size WxH                    size of object to rotate",
  159. "    -delta +X+Y                  amount by which to move object",
  160. "    -r                           draw in the root window",
  161. "    -d number                    dashed line pattern for wire frames",
  162. "    -bg color                    background color",
  163. "    -colors color ...            codes to use on sides",
  164. "    -p#                          use # (1 through 8) primary colors",
  165. "    -dbl                         use double buffering (extension if present)",
  166. "    -softdbl                     use software double buffering",
  167. "    -noedges                     don't draw wire frame edges",
  168. "    -faces                       draw faces",
  169. "    -copy                        copy multibuffer frames instead of clearing",
  170. "    -lw number                   line width to use",
  171. "    -i                           invert",
  172. "    -sleep number                seconds to sleep in between draws",
  173. "    -obj objname                 type of polyhedral object to draw",
  174. "    -objhelp                     list polyhedral objects available",
  175. NULL};
  176.  
  177. /******************************************************************************
  178.  * Description
  179.  *    Main routine.  Process command-line arguments, then bounce a bounding
  180.  *    box inside the window.  Call DrawIco() to redraw the icosahedron.
  181.  *****************************************************************************/
  182.  
  183. main(argc, argv)
  184. int argc;
  185. char **argv;
  186.     {
  187.     char *display = NULL;
  188.     char *geom = NULL;
  189.     int useRoot = 0;
  190.     long fg, bg;
  191.     int invert = 0;
  192.     int dash = 0;
  193.     XSetWindowAttributes xswa;
  194.     XWindowAttributes xwa;
  195.     Polyinfo *poly;        /* the poly to draw */
  196.     int icoX, icoY;
  197.     XEvent xev;
  198.     Bool blocking = False;
  199.     unsigned long vmask;
  200.     XGCValues xgcv;
  201.     int linewidth = 0;
  202.     char *background_colorname = NULL;
  203.     char *ico_geom = NULL;
  204.     char *delta_geom = NULL;
  205.     int icodeltax2, icodeltay2;
  206.     extern int _Xdebug;
  207.     int initcolors = 0;
  208. #ifdef MULTIBUFFER
  209.     int update_action = MultibufferUpdateActionBackground;
  210. #endif
  211.         time_t tt; /* added this variable for time() JDC 91/08/08*/
  212.     ProgramName = argv[0];
  213.  
  214.     /* Process arguments: */
  215.  
  216.     poly = findpoly("icosahedron");    /* default */
  217.  
  218.     while (*++argv) {
  219.         if (!strcmp (*argv, "-display")) {
  220.             display = *++argv;
  221.         } else if (!strncmp (*argv, "-g", 2)) {
  222.             geom = *++argv;
  223.         } else if (**argv == '=')         /* obsolete */
  224.             geom = *argv;
  225.         else if (!strcmp(*argv, "-r"))
  226.             useRoot = 1;
  227.         else if (!strcmp (*argv, "-d"))
  228.             dash = atoi(*++argv);
  229.         else if (!strcmp(*argv, "-colors")) {
  230.             colornames = ++argv;
  231.             for ( ; *argv && *argv[0]!='-'; argv++) ;
  232.             numcolors = argv - colornames;
  233.             --argv;
  234.         }
  235.         else if (!strcmp (*argv, "-copy")) {
  236. #ifdef MULTIBUFFER
  237.             update_action = MultibufferUpdateActionCopied;
  238. #endif
  239.         } else if (!strcmp (*argv, "-lw"))
  240.             linewidth = atoi(*++argv);
  241.         else if (!strcmp (*argv, "-dbl"))
  242. #ifdef MULTIBUFFER
  243.             multibuf = 1;
  244. #else
  245.             dblbuf = 1;
  246. #endif
  247.         else if (!strcmp(*argv, "-softdbl")) {
  248.             dblbuf = 1;
  249.             multibuf = 0;
  250.         }
  251.         else if (!strncmp(*argv, "-p", 2)) {
  252.             numcolors = atoi(argv[0]+2);
  253.             if (numcolors < 1 || numcolors > NumberPrimaries)
  254.               numcolors = NumberPrimaries;
  255.             colornames = Primaries;
  256.             dofaces = 1;
  257.         }
  258.         else if (!strcmp(*argv, "-bg"))
  259.             background_colorname = *++argv;
  260.         else if (!strcmp(*argv, "-noedges"))
  261.             doedges = 0;
  262.         else if (!strcmp(*argv, "-faces"))
  263.             dofaces = 1;
  264.         else if (!strcmp(*argv, "-i"))
  265.             invert = 1;
  266.         else if (!strcmp(*argv, "-size"))
  267.             ico_geom = *++argv;
  268.         else if (!strcmp(*argv, "-delta"))
  269.             delta_geom = *++argv;
  270.         else if (!strcmp (*argv, "-sleep")) {
  271.             float f = 0.0;
  272.             sscanf (*++argv, "%f", &f);
  273.             msleepcount = (int) (f * 1000.0);
  274.             sleepcount = msleepcount / 1000;
  275.         } else if (!strcmp (*argv, "-obj"))
  276.             poly = findpoly(*++argv);
  277.         else if (!strcmp(*argv, "-dsync"))
  278.             dsync = 1;
  279.         else if (!strncmp(*argv, "-sync",  5)) 
  280.             _Xdebug = 1;
  281.         else if (!strcmp(*argv, "-objhelp")) {
  282.             giveObjHelp();
  283.             exit(1);
  284.         }
  285.         else {    /* unknown arg */
  286.             char **cpp;
  287.  
  288.           usage:
  289.             fprintf (stderr, "usage:  %s [-options]\n\n", ProgramName);
  290.             for (cpp = help_message; *cpp; cpp++) {
  291.             fprintf (stderr, "%s\n", *cpp);
  292.             }
  293.             fprintf (stderr, "\n");
  294.             exit (1);
  295.         }
  296.     }
  297.  
  298.     if (!dofaces && !doedges) icoFatal("nothing to draw");
  299.  
  300.     if (!(dpy= XOpenDisplay(display)))
  301.             {
  302.         perror("Cannot open display\n");
  303.         exit(-1);
  304.             }
  305.  
  306. #ifdef MULTIBUFFER
  307.     if (multibuf && !XmbufQueryExtension (dpy, &mbevbase, &mberrbase)) {
  308.         multibuf = 0;
  309.         dblbuf = 1;
  310.     }
  311. #endif
  312.  
  313.     cmap = XDefaultColormap(dpy,DefaultScreen(dpy));
  314.     if (!cmap) {
  315.         icoFatal("no default colormap!");
  316.     }
  317.  
  318.     fg = WhitePixel(dpy, DefaultScreen(dpy));
  319.     bg = BlackPixel(dpy, DefaultScreen(dpy));
  320.     if (background_colorname) {
  321.         XColor cdef;
  322.  
  323.         if (XParseColor (dpy, cmap, background_colorname, &cdef) &&
  324.         XAllocColor (dpy, cmap, &cdef))
  325.           bg = cdef.pixel;
  326.         else 
  327.           icoFatal ("no such color \"%s\"", background_colorname);
  328.     }
  329.     if (numcolors && (!dofaces || numcolors == 1)) {
  330.         XColor cdef;
  331.  
  332.         if (XParseColor (dpy, cmap, colornames[0], &cdef) &&
  333.         XAllocColor (dpy, cmap, &cdef))
  334.           fg = cdef.pixel;
  335.         else 
  336.           icoFatal ("no such color \"%s\"", colornames[0]);
  337.     }
  338.  
  339.     if (invert) {
  340.         unsigned long tmp = fg;
  341.         fg = bg;
  342.         bg = tmp;
  343.     }
  344.  
  345.  
  346.     /* Set up window parameters, create and map window if necessary: */
  347.  
  348.     dispW = DisplayWidth(dpy, DefaultScreen(dpy)); /* POHC */
  349.     dispH = DisplayHeight(dpy, DefaultScreen(dpy));
  350.  
  351.     if (useRoot)
  352.         {
  353.         draw_window = DefaultRootWindow(dpy);
  354.         winX = 0;
  355.         winY = 0;
  356.         winW = dispW; /* POHC */
  357.         winH = dispH;
  358.         }
  359.     else {
  360.         winW = winH = 400; /* (multibuf ? 300 : 600); 90/06/26 POHC */
  361.         winX = (DisplayWidth(dpy, DefaultScreen(dpy)) - winW) >> 1;
  362.         winY = (DisplayHeight(dpy, DefaultScreen(dpy)) - winH) >> 1;
  363.         if (geom) 
  364.             XParseGeometry(geom, &winX, &winY,
  365.                        (unsigned int *)&winW,
  366.                        (unsigned int *)&winH);
  367.  
  368.         xswa.event_mask = ExposureMask | StructureNotifyMask;
  369.         xswa.background_pixel = bg;
  370.         xswa.border_pixel = fg;
  371.         draw_window = XCreateWindow(dpy, DefaultRootWindow(dpy), 
  372.             winX, winY, winW, winH, 0, 
  373.             DefaultDepth(dpy, DefaultScreen(dpy)), 
  374.             InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
  375.             CWEventMask | CWBackPixel | CWBorderPixel, &xswa);
  376.         XChangeProperty(dpy, draw_window, XA_WM_NAME, XA_STRING, 8, 
  377.                 PropModeReplace, (unsigned char *)"Ico", 3);
  378.         XMapWindow(dpy, draw_window);
  379.         while (1) {
  380.             XNextEvent(dpy, &xev);
  381.             if (xev.type == Expose)
  382.             break;
  383.         }
  384.         if (XGetWindowAttributes(dpy,draw_window,&xwa)==0) {
  385.             icoFatal("cant get window attributes (size)");
  386.         }
  387.         winW = xwa.width;
  388.         winH = xwa.height;
  389.         }
  390.  
  391.     if (ico_geom) 
  392.       XParseGeometry (ico_geom, &icoX, &icoY,
  393.               (unsigned int *)&icoW,
  394.               (unsigned int *)&icoH);
  395.     if (icoW <= 0) icoW = DEFAULT_ICO_WIDTH;
  396.     if (icoH <= 0) icoH = DEFAULT_ICO_HEIGHT;
  397.     if (icoW < MIN_ICO_WIDTH) icoW = MIN_ICO_WIDTH;
  398.     if (icoH < MIN_ICO_HEIGHT) icoH = MIN_ICO_HEIGHT;
  399.  
  400.     if (delta_geom) {
  401.         unsigned int junk;
  402.  
  403.         XParseGeometry (delta_geom, &icoDeltaX, &icoDeltaY, &junk, &junk);
  404.         if (icoDeltaX == 0 && icoDeltaY == 0) {
  405.         icoDeltaX = DEFAULT_DELTAX;
  406.         icoDeltaY = DEFAULT_DELTAY;
  407.         }
  408.     }
  409.  
  410.     win = None;
  411.  
  412. #ifdef MULTIBUFFER
  413.     if (multibuf) {
  414.         if (XmbufCreateBuffers (dpy, draw_window, 2, update_action,
  415.                     MultibufferUpdateHintFrequent,
  416.                     multibuffers) == 2) {
  417.         XCopyArea (dpy, draw_window, multibuffers[1],
  418.                DefaultGC(dpy, DefaultScreen(dpy)),
  419.                0, 0, winW, winH, 0, 0);
  420.         win = multibuffers[1];
  421.         } else 
  422.           icoFatal ("unable to obtain 2 buffers");
  423.         dblbuf = 1;
  424.     }
  425. #endif /* MULTIBUFFER */
  426.     if (win == None) win = draw_window;
  427.  
  428.     /* whether or not we are emulating */
  429.     softdbl = (dblbuf && !multibuf);
  430.  
  431.  
  432.     /* Set up a graphics context: */
  433.  
  434.     vmask = (GCBackground | GCForeground | GCLineWidth);
  435.     xgcv.background = bg;
  436.     xgcv.foreground = fg;
  437.     xgcv.line_width = linewidth;
  438.     if (dash) {
  439.         xgcv.line_style = LineDoubleDash;
  440.         xgcv.dashes = dash;
  441.         vmask |= (GCLineStyle | GCDashList);
  442.     }
  443.     gc = XCreateGC (dpy, draw_window, vmask, &xgcv);
  444.  
  445.     if (dofaces && numcolors>1) {
  446.         int i,t,bits;
  447.         bits = 0;
  448.         for (t=numcolors; t; t=t>>1) bits++;
  449.         initDBufs(fg,bg,bits);
  450.         /* don't set the background color */
  451.         for (i=0; i<numcolors; i++) {
  452.             setBufColname(i+1,colornames[i]);
  453.         }
  454.         initcolors = 1;
  455.     }
  456.     else if (dblbuf || dofaces) {
  457.         initDBufs(fg,bg,1);
  458.         initcolors = 1;
  459.     }
  460.     if (initcolors) {
  461.         setDisplayBuf(dblbuf?1:0);    /* insert new colors */
  462.     }
  463.     if (!numcolors) numcolors=1;
  464.  
  465.     if (dsync)
  466.         XSync(dpy, 0);
  467.  
  468.     /* POHC/GWP get initiali position moved down */
  469.  
  470.     /* Bounce the box in the window: */
  471.  
  472.     icodeltax2 = icoDeltaX * 2;
  473.     icodeltay2 = icoDeltaY * 2;
  474.     for (;;)
  475.         {
  476.         int prevX;
  477.         int prevY;
  478.  
  479.         if (blocking || XPending(dpy)) {
  480.             XNextEvent(dpy, &xev);
  481.  
  482.             switch (xev.type) {
  483.               case ConfigureNotify:
  484.             winW = xev.xconfigure.width;
  485.             winH = xev.xconfigure.height;
  486.             initialized = 0; /* POHC/GWP */
  487.             break;
  488.               case MapNotify:
  489.             blocking = False;
  490.             break;
  491.               case UnmapNotify:
  492.             blocking = True;
  493.             continue;
  494.             }
  495.         }
  496.  
  497.         prevX = icoX;
  498.         prevY = icoY;
  499.  
  500.         /* Get the initial position, size, and speed of the bounding-box: */
  501.         if (!initialized) {
  502.             if (!ico_geom) {
  503.                 int i;
  504.                 icoW = icoH = (winH<winW ? winH:winW)/3;
  505.                 i = (dispW<dispH?dispW:dispH)/5;
  506.                 if (icoW > i) icoW = icoH = i;
  507.             }
  508.             srandom((int) time(&tt) % 231); /* added tt var JDC 91/08/08*/
  509. #ifdef MSDOS /* POHC/GWP 91/01/10 */
  510.             icoX = (int) (((unsigned) ((winW - icoW) * (random() & 0x1F))) >> 5);
  511.             icoY = (int) (((unsigned) ((winH - icoH) * (random() & 0x1F))) >> 5);
  512. #else /* MSDOS */
  513.             icoX = ((winW - icoW) * (random() & 0xFF)) >> 8;
  514.             icoY = ((winH - icoH) * (random() & 0xFF)) >> 8;
  515. #endif /* MSDOS */
  516.         }
  517.  
  518.         icoX += icoDeltaX;
  519.         if (icoX < 0 || icoX + icoW > winW)
  520.             {
  521.             icoX -= icodeltax2;
  522.             icoDeltaX = - icoDeltaX;
  523.             icodeltax2 = icoDeltaX * 2;
  524.             }
  525.         icoY += icoDeltaY;
  526.         if (icoY < 0 || icoY + icoH > winH)
  527.             {
  528.             icoY -= icodeltay2;
  529.             icoDeltaY = - icoDeltaY;
  530.             icodeltay2 = icoDeltaY * 2;
  531.             }
  532.  
  533.         drawPoly(poly, gc, icoX, icoY, icoW, icoH, prevX, prevY);
  534.         }
  535.     }
  536.  
  537. giveObjHelp()
  538. {
  539. int i;
  540. Polyinfo *poly;
  541.     printf("%-16s%-12s  #Vert.  #Edges  #Faces  %-16s\n",
  542.         "Name", "ShortName", "Dual");
  543.     for (i=0; i<polysize; i++) {
  544.         poly = polys+i;
  545.         printf("%-16s%-12s%6d%8d%8d    %-16s\n",
  546.             poly->longname, poly->shortname,
  547.             poly->numverts, poly->numedges, poly->numfaces,
  548.             poly->dual);
  549.     }
  550. }
  551.  
  552. Polyinfo *
  553. findpoly(name)
  554. char *name;
  555. {
  556. int i;
  557. Polyinfo *poly;
  558.     for (i=0; i<polysize; i++) {
  559.         poly = polys+i;
  560.         if (strcmp(name,poly->longname)==0 ||
  561.             strcmp(name,poly->shortname)==0) return poly;
  562.     }
  563.     icoFatal("can't find object %s", name);
  564. }
  565.  
  566. icoClearArea(x,y,w,h)
  567. int x,y,w,h;
  568. {
  569.     if (multibuf) return;
  570.  
  571.     if (dblbuf || dofaces) {
  572.         XSetForeground(dpy, gc, dbpair.drawbuf->pixels[0]);
  573.             /* use background as foreground color for fill */
  574.         XFillRectangle(dpy,win,gc,x,y,w,h);
  575.     }
  576.     else {
  577.         XClearArea(dpy,win,x,y,w,h,0);
  578.     }
  579. }
  580.  
  581. /******************************************************************************
  582.  * Description
  583.  *    Undraw previous polyhedron (by erasing its bounding box).
  584.  *    Rotate and draw the new polyhedron.
  585.  *
  586.  * Input
  587.  *    poly        the polyhedron to draw
  588.  *    gc        X11 graphics context to be used for drawing
  589.  *    icoX, icoY    position of upper left of bounding-box
  590.  *    icoW, icoH    size of bounding-box
  591.  *    prevX, prevY    position of previous bounding-box
  592.  *****************************************************************************/
  593. char drawn[MAXNV][MAXNV];
  594.  
  595. drawPoly(poly, gc, icoX, icoY, icoW, icoH, prevX, prevY)
  596. Polyinfo *poly;
  597. GC gc;
  598. int icoX, icoY, icoW, icoH;
  599. int prevX, prevY;
  600.     {
  601.     /* static int initialized = 0; POHC/GWP */
  602.  
  603.     Point3D *v = poly->v;
  604.     int *f = poly->f;
  605.     int NV = poly->numverts;
  606.     int NF = poly->numfaces;
  607.  
  608.     static Transform3D xform;
  609.     static Point3D xv[2][MAXNV];
  610.     static int buffer;
  611.     register int p0;
  612.     register int p1;
  613.     register XPoint *pv2;
  614.     XSegment *pe;
  615.     register Point3D *pxv;
  616.     static double wo2, ho2;
  617.     XPoint v2[MAXNV];
  618.     XSegment edges[MAXEDGES];
  619.     register int i;
  620.     int j,k;
  621.     register int *pf;
  622.     int facecolor;
  623.  
  624.     int pcount;
  625.     double pxvz;
  626.     XPoint ppts[MAXEDGESPERPOLY];
  627.  
  628.     /* Set up points, transforms, etc.:  */
  629.  
  630.     if (!initialized)    
  631.         {
  632.         Transform3D r1;
  633.         Transform3D r2;
  634.  
  635.         FormatRotateMat('x', 5 * 3.1416 / 180.0, r1);
  636.         FormatRotateMat('y', 5 * 3.1416 / 180.0, r2);
  637.         ConcatMat(r1, r2, xform);
  638.  
  639.         bcopy((char *) v, (char *) xv[0], NV * sizeof(Point3D));
  640.         buffer = 0;
  641.  
  642.         wo2 = icoW / 2.0;
  643.         ho2 = icoH / 2.0;
  644.  
  645.         initialized = 1;
  646.         }
  647.  
  648.  
  649.     /* Switch double-buffer and rotate vertices: */
  650.  
  651.     buffer = !buffer;
  652.     PartialNonHomTransform(NV, xform, xv[!buffer], xv[buffer]);
  653.  
  654.  
  655.     /* Convert 3D coordinates to 2D window coordinates: */
  656.  
  657.     pxv = xv[buffer];
  658.     pv2 = v2;
  659.     for (i = NV - 1; i >= 0; --i)
  660.         {
  661.         pv2->x = (int) ((pxv->x + 1.0) * wo2) + icoX;
  662.         pv2->y = (int) ((pxv->y + 1.0) * ho2) + icoY;
  663.         ++pxv;
  664.         ++pv2;
  665.         }
  666.  
  667.  
  668.     /* Accumulate edges to be drawn, eliminating duplicates for speed: */
  669.  
  670.     pxv = xv[buffer];
  671.     pv2 = v2;
  672.     pf = f;
  673.     pe = edges;
  674.     bzero(drawn, sizeof(drawn));
  675.  
  676.     if (dblbuf)
  677.         setDrawBuf(dbpair.dbufnum);
  678.             /* switch drawing buffers if double buffered */
  679.     /* for faces, need to clear before FillPoly */
  680.     if (dofaces && !multibuf) {    /* multibuf uses update background */
  681.         if (softdbl)
  682.             icoClearArea(
  683.                 dbpair.drawbuf->prevX, dbpair.drawbuf->prevY,
  684.                 icoW + 1, icoH + 1);
  685.         icoClearArea(prevX, prevY, icoW + 1, icoH + 1);
  686.     }
  687.  
  688.     if (dsync)
  689.         XSync(dpy, 0);
  690.  
  691.     for (i = NF - 1; i >= 0; --i, pf += pcount)
  692.         {
  693.  
  694.         pcount = *pf++;    /* number of edges for this face */
  695.         pxvz = 0.0;
  696.         for (j=0; j<pcount; j++) {
  697.             p0 = pf[j];
  698.             pxvz += pxv[p0].z;
  699.         }
  700.  
  701.         /* If facet faces away from viewer, don't consider it: */
  702.         if (pxvz<0.0)
  703.             continue;
  704.  
  705.         if (dofaces) {
  706.             if (numcolors)
  707.                 facecolor = i%numcolors + 1;
  708.             else    facecolor = 1;
  709.             XSetForeground(dpy, gc,
  710.                 dbpair.drawbuf->pixels[facecolor]);
  711.             for (j=0; j<pcount; j++) {
  712.                 p0 = pf[j];
  713.                 ppts[j].x = pv2[p0].x;
  714.                 ppts[j].y = pv2[p0].y;
  715.             }
  716.             XFillPolygon(dpy, win, gc, ppts, pcount,
  717.                 Convex, CoordModeOrigin);
  718.         }
  719.  
  720.         if (doedges) {
  721.             for (j=0; j<pcount; j++) {
  722.                 if (j<pcount-1) k=j+1;
  723.                 else k=0;
  724.                 p0 = pf[j];
  725.                 p1 = pf[k];
  726.                 if (!drawn[p0][p1]) {
  727.                     drawn[p0][p1] = 1;
  728.                     drawn[p1][p0] = 1;
  729.                     pe->x1 = pv2[p0].x;
  730.                     pe->y1 = pv2[p0].y;
  731.                     pe->x2 = pv2[p1].x;
  732.                     pe->y2 = pv2[p1].y;
  733.                     ++pe;
  734.                 }
  735.             }
  736.         }
  737.         }
  738.  
  739.     /* Erase previous, draw current icosahedrons; sync for smoothness. */
  740.  
  741.     if (doedges) {
  742.         if (dofaces) {
  743.             XSetForeground(dpy, gc, dbpair.drawbuf->pixels[0]);
  744.                 /* use background as foreground color */
  745.         }
  746.         else {
  747.             if (softdbl)
  748.                 icoClearArea(dbpair.drawbuf->prevX,
  749.                     dbpair.drawbuf->prevY,
  750.                     icoW + 1, icoH + 1);
  751.             if (!multibuf)
  752.               icoClearArea(prevX, prevY, icoW + 1, icoH + 1);
  753.             if (dblbuf || dofaces) {
  754.                 XSetForeground(dpy, gc, dbpair.drawbuf->pixels[
  755.                     dbpair.pixelsperbuf-1]);
  756.             }
  757.         }
  758.         XDrawSegments(dpy, win, gc, edges, pe - edges);
  759.     }
  760.  
  761.     if (dsync)
  762.         XSync(dpy, 0);
  763.  
  764.     if (dblbuf) {
  765.         dbpair.drawbuf->prevX = icoX;
  766.         dbpair.drawbuf->prevY = icoY;
  767.         setDisplayBuf(dbpair.dbufnum);
  768.     }
  769.     if (dblbuf)
  770.         dbpair.dbufnum = 1 - dbpair.dbufnum;
  771.     if (!multibuf && sleepcount) sleep(sleepcount);
  772.     }
  773.  
  774. char *xalloc(nbytes)
  775. int nbytes;
  776. {
  777. char *p;
  778.  
  779.     p = malloc((unsigned int)nbytes);
  780.     if (p) return p;
  781.     fprintf(stderr,"ico: no more memory\n");
  782.     exit(1);
  783. }
  784.  
  785. initDBufs(fg,bg,planesperbuf)
  786. long fg,bg; /* Was int. POHC 91/01/25 */
  787. int planesperbuf;
  788. {
  789. int i,j,jj,j0,j1,k,m,t;
  790. DBufInfo *b, *otherb;
  791.  
  792.     nplanesets = (softdbl ? 2 : 1);
  793.  
  794.     dbpair.planesperbuf = planesperbuf;
  795.     dbpair.pixelsperbuf = 1<<planesperbuf;
  796.     dbpair.totalplanes = nplanesets * planesperbuf;
  797.     dbpair.totalpixels = 1<<dbpair.totalplanes;
  798.     dbpair.plane_masks = (unsigned long *)
  799.         xalloc(dbpair.totalplanes * sizeof(unsigned long));
  800.     dbpair.dbufnum = 0;
  801.     for (i=0; i < nplanesets; i++) {
  802.         b = dbpair.bufs+i;
  803.         b->plane_masks = dbpair.plane_masks + (i*planesperbuf);
  804.         b->colors = (XColor *)
  805.             xalloc(dbpair.totalpixels * sizeof(XColor));
  806.         b->pixels = (unsigned long *)
  807.             xalloc(dbpair.pixelsperbuf * sizeof(unsigned long));
  808.     }
  809.  
  810.     if (dbpair.totalplanes == 1) {
  811.         dbpair.pixels[0] = bg;
  812.         dbpair.plane_masks[0] = fg ^ bg;
  813.     } else {
  814.         t = XAllocColorCells(dpy,cmap,0,
  815.             dbpair.plane_masks,dbpair.totalplanes, dbpair.pixels,1);
  816.                 /* allocate color planes */
  817.         if (t==0) {
  818.             icoFatal("can't allocate enough color planes");
  819.         }
  820.     }
  821.  
  822.     fgcolor.pixel = fg;
  823.     bgcolor.pixel = bg;
  824.     XQueryColor(dpy,cmap,&fgcolor);
  825.     XQueryColor(dpy,cmap,&bgcolor);
  826.  
  827.     setBufColor(0,&bgcolor);
  828.     setBufColor(1,&fgcolor);
  829.     for (i=0; i<nplanesets; i++) {
  830.         b = dbpair.bufs+i;
  831.         if (dblbuf)
  832.             otherb = dbpair.bufs+(1-i);
  833.         for (j0=0; j0<(softdbl?dbpair.pixelsperbuf:1); j0++) {
  834.             for (j1=0; j1<dbpair.pixelsperbuf; j1++) {
  835.             j = (j0<<dbpair.planesperbuf)|j1;
  836.             if (i==0) jj=j;
  837.             else jj= (j1<<dbpair.planesperbuf)|j0;
  838.             b->colors[jj].pixel = dbpair.pixels[0];
  839.             for (k=0, m=j; m; k++, m=m>>1) {
  840.                 if (m&1)
  841.                    b->colors[jj].pixel ^= dbpair.plane_masks[k];
  842.             }
  843.             b->colors[jj].flags = DoRed | DoGreen | DoBlue;
  844.             }
  845.         }
  846.         b->prevX = b->prevY = 0;
  847.         b->enplanemask = 0;
  848.         for (j=0; j<planesperbuf; j++) {
  849.             b->enplanemask |= b->plane_masks[j];
  850.         }
  851.         for (j=0; j<dbpair.pixelsperbuf; j++) {
  852.             b->pixels[j] = dbpair.pixels[0];
  853.             for (k=0, m=j; m; k++, m=m>>1) {
  854.                 if (m&1)
  855.                    b->pixels[j] ^= b->plane_masks[k];
  856.             }
  857.         }
  858.     }
  859.  
  860.     if (!multibuf) {
  861.         setDrawBuf(0);
  862.         XSetBackground(dpy, gc, dbpair.bufs[0].pixels[0]);
  863.         XSetPlaneMask(dpy, gc, AllPlanes);
  864.         icoClearArea(0, 0, winW, winH); /* clear entire window */
  865.     }
  866.  
  867. /*    if (softdbl) setDisplayBuf(1); */
  868. }
  869.  
  870. setBufColname(n,colname)
  871. int n;
  872. char *colname;
  873. {
  874. int t;
  875. XColor dcolor, color;
  876.  
  877.     t = XLookupColor(dpy,cmap,colname,&dcolor,&color);
  878.     if (t==0) {    /* no such color */
  879.         icoFatal("no such color %s",colname);
  880.     }
  881.     setBufColor(n,&color);
  882. }
  883.  
  884. setBufColor(n,color)
  885. int n;        /* color index */
  886. XColor *color;    /* color to set */
  887. {
  888. int i,j,cx;
  889. DBufInfo *b;
  890. unsigned long pix;
  891.  
  892.     for (i=0; i<nplanesets; i++) {
  893.         b = dbpair.bufs+i;
  894.         for (j=0; j<(softdbl?dbpair.pixelsperbuf:1); j++) {
  895.             cx = n + j*dbpair.pixelsperbuf;
  896.             pix = b->colors[cx].pixel;
  897.             b->colors[cx] = *color;
  898.             b->colors[cx].pixel = pix;
  899.             b->colors[cx].flags = DoRed | DoGreen | DoBlue;
  900.         }
  901.     }
  902. }
  903.  
  904. setDrawBuf (n)
  905.     int n;
  906. {
  907.     XGCValues xgcv;
  908.     unsigned long mask;
  909.  
  910. #ifdef MULTIBUFFER
  911.     if (multibuf) {
  912.     win = multibuffers[n];
  913.     n = 0;
  914.     }
  915. #endif /* MULTIBUFFER */
  916.  
  917.     dbpair.drawbuf = dbpair.bufs+n;
  918.     xgcv.foreground = dbpair.drawbuf->pixels[dbpair.pixelsperbuf-1];
  919.     xgcv.background = dbpair.drawbuf->pixels[0];
  920.     mask = GCForeground | GCBackground;
  921.     if (softdbl) {
  922.     xgcv.plane_mask = dbpair.drawbuf->enplanemask;
  923.     mask |= GCPlaneMask;
  924.     }
  925.     XChangeGC(dpy, gc, mask, &xgcv);
  926. }
  927.  
  928. setDisplayBuf(n)
  929. int n;
  930. {
  931. #if defined(MULTIBUFFER)
  932.     if (multibuf) {
  933.     static int firsttime = 1;
  934.  
  935.     XmbufDisplayBuffers (dpy, 1, &multibuffers[n], msleepcount, 0);
  936.     if (firsttime) {
  937.         firsttime = 0;
  938.         n = 0;
  939.         goto storecolors;
  940.     }
  941.     } else
  942. #endif
  943.     {
  944.       storecolors:
  945.     dbpair.dpybuf= dbpair.bufs+n;
  946.     if (dbpair.totalpixels > 2)
  947.         XStoreColors(dpy,cmap,dbpair.dpybuf->colors,dbpair.totalpixels);
  948.     }
  949. }
  950.  
  951. void icoFatal(char *fmt, ...)   /* added varargs MTP 92/07/30 */
  952. {
  953.     va_list argptr;
  954.     fprintf(stderr,"ico: ");
  955.     va_start(argptr,fmt);
  956.     vfprintf(stderr,fmt,argptr);
  957.     va_end(argptr);
  958.     fprintf(stderr,"\n");
  959.     exit(1);
  960. }
  961.  
  962. /******************************************************************************
  963.  * Description
  964.  *    Concatenate two 4-by-4 transformation matrices.
  965.  *
  966.  * Input
  967.  *    l        multiplicand (left operand)
  968.  *    r        multiplier (right operand)
  969.  *
  970.  * Output
  971.  *    *m        Result matrix
  972.  *****************************************************************************/
  973.  
  974. ConcatMat(l, r, m)
  975. register Transform3D l;
  976. register Transform3D r;
  977. register Transform3D m;
  978.     {
  979.     register int i;
  980.     register int j;
  981.  
  982.     for (i = 0; i < 4; ++i)
  983.         for (j = 0; j < 4; ++j)
  984.             m[i][j] = l[i][0] * r[0][j]
  985.                 + l[i][1] * r[1][j]
  986.                 + l[i][2] * r[2][j]
  987.                 + l[i][3] * r[3][j];
  988.     }
  989.  
  990.  
  991.  
  992. /******************************************************************************
  993.  * Description
  994.  *    Format a matrix that will perform a rotation transformation
  995.  *    about the specified axis.  The rotation angle is measured
  996.  *    counterclockwise about the specified axis when looking
  997.  *    at the origin from the positive axis.
  998.  *
  999.  * Input
  1000.  *    axis        Axis ('x', 'y', 'z') about which to perform rotation
  1001.  *    angle        Angle (in radians) of rotation
  1002.  *    A        Pointer to rotation matrix
  1003.  *
  1004.  * Output
  1005.  *    *m        Formatted rotation matrix
  1006.  *****************************************************************************/
  1007.  
  1008. FormatRotateMat(axis, angle, m)
  1009. char axis;
  1010. double angle;
  1011. register Transform3D m;
  1012.     {
  1013.     double s, c;
  1014.     double sin(), cos();
  1015.  
  1016.     IdentMat(m);
  1017.  
  1018.     s = sin(angle);
  1019.     c = cos(angle);
  1020.  
  1021.     switch(axis)
  1022.         {
  1023.         case 'x':
  1024.             m[1][1] = m[2][2] = c;
  1025.             m[1][2] = s;
  1026.             m[2][1] = -s;
  1027.             break;
  1028.         case 'y':
  1029.             m[0][0] = m[2][2] = c;
  1030.             m[2][0] = s;
  1031.             m[0][2] = -s;
  1032.             break;
  1033.         case 'z':
  1034.             m[0][0] = m[1][1] = c;
  1035.             m[0][1] = s;
  1036.             m[1][0] = -s;
  1037.             break;
  1038.         }
  1039.     }
  1040.  
  1041.  
  1042.  
  1043. /******************************************************************************
  1044.  * Description
  1045.  *    Format a 4x4 identity matrix.
  1046.  *
  1047.  * Output
  1048.  *    *m        Formatted identity matrix
  1049.  *****************************************************************************/
  1050.  
  1051. IdentMat(m)
  1052. register Transform3D m;
  1053.     {
  1054.     register int i;
  1055.     register int j;
  1056.  
  1057.     for (i = 3; i >= 0; --i)
  1058.         {
  1059.         for (j = 3; j >= 0; --j)
  1060.             m[i][j] = 0.0;
  1061.         m[i][i] = 1.0;
  1062.         }
  1063.     }
  1064.  
  1065.  
  1066.  
  1067. /******************************************************************************
  1068.  * Description
  1069.  *    Perform a partial transform on non-homogeneous points.
  1070.  *    Given an array of non-homogeneous (3-coordinate) input points,
  1071.  *    this routine multiplies them by the 3-by-3 upper left submatrix
  1072.  *    of a standard 4-by-4 transform matrix.  The resulting non-homogeneous
  1073.  *    points are returned.
  1074.  *
  1075.  * Input
  1076.  *    n        number of points to transform
  1077.  *    m        4-by-4 transform matrix
  1078.  *    in        array of non-homogeneous input points
  1079.  *
  1080.  * Output
  1081.  *    *out        array of transformed non-homogeneous output points
  1082.  *****************************************************************************/
  1083.  
  1084. PartialNonHomTransform(n, m, in, out)
  1085. int n;
  1086. register Transform3D m;
  1087. register Point3D *in;
  1088. register Point3D *out;
  1089.     {
  1090.     for (; n > 0; --n, ++in, ++out)
  1091.         {
  1092.         out->x = in->x * m[0][0] + in->y * m[1][0] + in->z * m[2][0];
  1093.         out->y = in->x * m[0][1] + in->y * m[1][1] + in->z * m[2][1];
  1094.         out->z = in->x * m[0][2] + in->y * m[1][2] + in->z * m[2][2];
  1095.         }
  1096.     }
  1097.